import os
import shutil
from typing import Dict, Any, List
import re
import importlib

class RuleEngine:
    def __init__(self):
        """规则引擎，用于处理高置信度的异常"""
        
        # 定义异常类型到脚本目录的映射
        self.anomaly_to_scripts = {
            "performance_degradation": {
                "cpu": ["cpu_负载过高.sh", "cpu_高中断.sh"],
                "mem": ["mem_内存耗尽大量换页.sh", "mem_OOM Killer触发.sh"],
                "system_metrices": ["system_metrices_tuned动态优化.sh"]
            },
            "memory_leak": {
                "mem": ["mem_Slab内存泄漏.sh", "mem_OOM Killer触发.sh"],
                "processes": ["processes_进程资源泄漏.sh"]
            },
            "cpu_usage": {
                "cpu": ["cpu_负载过高.sh", "cpu_高中断.sh", "cpu_进程调度延迟.sh"],
                "processes": ["processes_进程资源泄漏.sh"]
            },
            "disk_io": {
                "diskio": ["diskio_IO延迟飙升.sh", "diskio_IO吞吐量瓶颈.sh", "diskio_IO Hang.sh"]
            },
            "network_issue": {
                "net": ["net_网络丢包.sh", "net_网卡降速.sh", "net_端口耗尽.sh"]
            },
            "kernel_issue": {
                "kernel": ["kernel_软死锁.sh", "kernel_TCP.IP参数耗尽.sh"]
            },
            "process_issue": {
                "processes": ["processes_僵尸进程累积.sh", "processes_进程资源泄漏.sh"]
            },
            "system_metric": {
                "system_metrices": ["system_metrices_tuned动态优化.sh", "system_文件描述符耗尽.sh"]
            }
        }
        
        # 定义关键词到异常类型的映射
        self.keyword_to_anomaly = {
            "cpu": "cpu_usage",
            "memory": "memory_leak",
            "disk": "disk_io",
            "network": "network_issue",
            "kernel": "kernel_issue",
            "process": "process_issue",
            "system": "system_metric",
            "performance": "performance_degradation"
        }

    async def process_anomaly(self, anomaly: Dict[str, Any], ansible_dir: str) -> Dict[str, Any]:
        """
        处理异常指标
        """
        try:
            # 1. 确定异常类型
            anomaly_type = self._determine_anomaly_type(anomaly)
            print(f"    确定的异常类型: {anomaly_type}")

            # 2. 动态导入对应agent
            agent_map = {
                "cpu": ("agent_mcp.tools.cpu.cpu_agent", "select_script_for_anomaly"),
                "mem": ("agent_mcp.tools.mem.mem_agent", "select_script_for_anomaly"),
                "diskio": ("agent_mcp.tools.diskio.diskio_agent", "select_script_for_anomaly"),
                "net": ("agent_mcp.tools.net.net_agent", "select_script_for_anomaly"),
                "kernel": ("agent_mcp.tools.kernel.kernel_agent", "select_script_for_anomaly"),
                "processes": ("agent_mcp.tools.processes.processes_agent", "select_script_for_anomaly"),
                "system_metrices": ("agent_mcp.tools.system_metrices.system_metrices_agent", "select_script_for_anomaly"),
            }
            
            best_script = None
            best_category = None
            
            # 遍历所有相关类别，找到最优脚本
            available_categories = self.anomaly_to_scripts.get(anomaly_type, {})
            print(f"    可用类别: {list(available_categories.keys())}")
            
            for category in available_categories:
                print(f"    检查类别: {category}")
                if category in agent_map:
                    try:
                        module_name, func_name = agent_map[category]
                        print(f"    导入模块: {module_name}")
                        agent_module = importlib.import_module(module_name)
                        select_func = getattr(agent_module, func_name)
                        script_name = select_func(anomaly)
                        print(f"    选择的脚本: {script_name}")
                        
                        # 检查脚本是否存在
                        script_path = f"agent_mcp/tools/{category}/{script_name}"
                        print(f"    脚本路径: {script_path}")
                        
                        if os.path.exists(script_path):
                            best_script = script_name
                            best_category = category
                            print(f"    ✅ 找到可用脚本: {script_name}")
                            break  # 找到第一个合适的即用
                        else:
                            print(f"    ❌ 脚本不存在: {script_path}")
                            # 尝试查找目录中的所有脚本
                            category_dir = f"agent_mcp/tools/{category}"
                            if os.path.exists(category_dir):
                                available_scripts = [f for f in os.listdir(category_dir) if f.endswith('.sh')]
                                print(f"    目录中的脚本: {available_scripts}")
                                if available_scripts:
                                    # 使用第一个可用的脚本
                                    best_script = available_scripts[0]
                                    best_category = category
                                    print(f"    ✅ 使用备用脚本: {best_script}")
                                    break
                    except Exception as e:
                        print(f"    ❌ 处理类别 {category} 时出错: {e}")
                        # 如果agent模块不存在，直接使用目录中的脚本
                        category_dir = f"agent_mcp/tools/{category}"
                        if os.path.exists(category_dir):
                            available_scripts = [f for f in os.listdir(category_dir) if f.endswith('.sh')]
                            if available_scripts:
                                best_script = available_scripts[0]
                                best_category = category
                                print(f"    ✅ 使用目录中的脚本: {best_script}")
                                break
                else:
                    print(f"    ❌ 类别 {category} 不在agent_map中")
            
            if not best_script:
                return {
                    "success": False,
                    "error": f"未找到异常类型 {anomaly_type} 的合适调优脚本",
                    "anomaly_id": anomaly.get("anomaly_id"),
                    "processing_method": "rule_engine"
                }
            
            # 3. 复制最优脚本到Ansible目录
            source_path = f"agent_mcp/tools/{best_category}/{best_script}"
            # 直接使用原脚本名称，如果同名则覆盖
            dest_path = os.path.join(ansible_dir, best_script)
            
            print(f"    复制脚本: {source_path} -> {dest_path}")
            
            try:
                import shutil
                shutil.copy2(source_path, dest_path)
                os.chmod(dest_path, 0o755)
                print(f"    ✅ 脚本复制成功")
            except Exception as e:
                return {
                    "success": False,
                    "error": f"复制脚本失败: {e}",
                    "anomaly_id": anomaly.get("anomaly_id"),
                    "processing_method": "rule_engine"
                }
            
            return {
                "success": True,
                "anomaly_id": anomaly.get("anomaly_id"),
                "anomaly_type": anomaly_type,
                "selected_script": best_script,
                "copied_script": dest_path,
                "final_script_name": best_script,
                "processing_method": "rule_engine"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "anomaly_id": anomaly.get("anomaly_id"),
                "processing_method": "rule_engine"
            }

    def _determine_anomaly_type(self, anomaly: Dict[str, Any]) -> str:
        """确定异常类型"""
        issue_type = anomaly.get("issue_type", "").lower()
        root_cause = anomaly.get("root_cause", "").lower()
        
        # 直接匹配问题类型
        if issue_type in self.anomaly_to_scripts:
            return issue_type
        
        # 通过关键词匹配
        all_text = f"{issue_type} {root_cause}".lower()
        
        for keyword, anomaly_type in self.keyword_to_anomaly.items():
            if keyword in all_text:
                return anomaly_type
        
        # 通过根因分析
        if "cpu" in root_cause or "processor" in root_cause:
            return "cpu_usage"
        elif "memory" in root_cause or "ram" in root_cause:
            return "memory_leak"
        elif "disk" in root_cause or "io" in root_cause:
            return "disk_io"
        elif "network" in root_cause or "connection" in root_cause:
            return "network_issue"
        elif "kernel" in root_cause:
            return "kernel_issue"
        elif "process" in root_cause:
            return "process_issue"
        else:
            return "performance_degradation"  # 默认类型

    def _select_scripts(self, anomaly_type: str, anomaly: Dict[str, Any]) -> List[Dict[str, Any]]:
        """选择合适的脚本"""
        selected_scripts = []
        
        if anomaly_type not in self.anomaly_to_scripts:
            return selected_scripts
        
        scripts_mapping = self.anomaly_to_scripts[anomaly_type]
        
        for category, script_names in scripts_mapping.items():
            for script_name in script_names:
                script_path = f"agent_mcp/tools/{category}/{script_name}"
                
                # 检查脚本是否存在
                if os.path.exists(script_path):
                    selected_scripts.append({
                        "category": category,
                        "script_name": script_name,
                        "script_path": script_path,
                        "priority": self._calculate_script_priority(script_name, anomaly)
                    })
        
        # 按优先级排序
        selected_scripts.sort(key=lambda x: x["priority"], reverse=True)
        
        return selected_scripts

    def _calculate_script_priority(self, script_name: str, anomaly: Dict[str, Any]) -> int:
        """计算脚本优先级"""
        priority = 0
        severity = anomaly.get("severity", 0)
        root_cause = anomaly.get("root_cause", "").lower()
        
        # 基于严重程度
        if severity >= 8:
            priority += 10
        elif severity >= 6:
            priority += 7
        elif severity >= 4:
            priority += 4
        
        # 基于脚本名称匹配
        script_lower = script_name.lower()
        
        # 高优先级关键词
        high_priority_keywords = ["oom", "critical", "emergency", "high"]
        for keyword in high_priority_keywords:
            if keyword in script_lower:
                priority += 5
        
        # 基于根因匹配
        if any(keyword in root_cause for keyword in script_lower.split("_")):
            priority += 3
        
        return priority

    async def _copy_scripts_to_ansible(self, selected_scripts: List[Dict[str, Any]], ansible_dir: str) -> List[str]:
        """复制脚本到Ansible目录"""
        copied_scripts = []
        
        for script_info in selected_scripts:
            source_path = script_info["script_path"]
            script_name = script_info["script_name"]
            dest_path = os.path.join(ansible_dir, script_name)
            
            try:
                # 复制脚本文件
                shutil.copy2(source_path, dest_path)
                copied_scripts.append(dest_path)
                
                # 确保脚本有执行权限
                os.chmod(dest_path, 0o755)
                
            except Exception as e:
                print(f"复制脚本失败: {source_path} -> {dest_path}, 错误: {e}")
        
        return copied_scripts

    def _generate_execution_plan(self, anomaly: Dict[str, Any], selected_scripts: List[Dict[str, Any]]) -> Dict[str, Any]:
        """生成执行计划"""
        execution_plan = {
            "anomaly_summary": {
                "id": anomaly.get("anomaly_id"),
                "issue_type": anomaly.get("issue_type"),
                "severity": anomaly.get("severity"),
                "root_cause": anomaly.get("root_cause")
            },
            "execution_steps": [],
            "estimated_duration": "0",
            "risk_level": "low"
        }
        
        total_duration = 0
        
        for i, script_info in enumerate(selected_scripts, 1):
            step = {
                "step_number": i,
                "script_name": script_info["script_name"],
                "category": script_info["category"],
                "priority": script_info["priority"],
                "estimated_duration": "5-10 minutes",
                "description": self._get_script_description(script_info["script_name"]),
                "risk_level": "low"
            }
            
            execution_plan["execution_steps"].append(step)
            total_duration += 10  # 每个脚本预估10分钟
        
        execution_plan["estimated_duration"] = f"{total_duration} minutes"
        
        # 根据严重程度调整风险等级
        severity = anomaly.get("severity", 0)
        if severity >= 8:
            execution_plan["risk_level"] = "high"
        elif severity >= 6:
            execution_plan["risk_level"] = "medium"
        
        return execution_plan

    def _get_script_description(self, script_name: str) -> str:
        """获取脚本描述"""
        descriptions = {
            "cpu_高中断.sh": "优化CPU高中断问题，调整中断负载分布",
            "cpu_负载过高.sh": "优化CPU负载过高问题，调整进程调度",
            "cpu_进程调度延迟.sh": "优化进程调度延迟，提高系统响应性",
            "mem_OOM Killer触发.sh": "处理OOM Killer触发问题，优化内存管理",
            "mem_Slab内存泄漏.sh": "检测和修复Slab内存泄漏问题",
            "mem_内存耗尽大量换页.sh": "处理内存耗尽和大量换页问题",
            "diskio_IO延迟飙升.sh": "优化IO延迟飙升问题，提高磁盘性能",
            "diskio_IO吞吐量瓶颈.sh": "解决IO吞吐量瓶颈问题",
            "diskio_IO Hang.sh": "处理IO Hang问题，恢复磁盘访问",
            "disk_磁盘空间耗尽.sh": "处理磁盘空间耗尽问题",
            "disk_Inode耗尽.sh": "处理Inode耗尽问题",
            "net_网络丢包.sh": "优化网络丢包问题，提高网络稳定性",
            "net_网卡降速.sh": "处理网卡降速问题，恢复网络性能",
            "net_端口耗尽.sh": "处理端口耗尽问题",
            "kernel_软死锁.sh": "处理内核软死锁问题",
            "kernel_TCP.IP参数耗尽.sh": "处理TCP/IP参数耗尽问题",
            "processes_进程资源泄漏.sh": "检测和修复进程资源泄漏问题",
            "processes_僵尸进程累积.sh": "清理僵尸进程累积问题",
            "system_metrices_tuned动态优化.sh": "使用tuned进行动态系统优化",
            "system_文件描述符耗尽.sh": "处理文件描述符耗尽问题"
        }
        
        return descriptions.get(script_name, "系统性能优化脚本") 